<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>p9总结 | GS0401</title><meta name="author" content="John Doe"><meta name="copyright" content="John Doe"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="p9总结在p9中我们背了以前的面试题，以及复习了原生js的使用，以及写的动画，拖拽。⼀、Vue2.0⾯试题  vue⽣命周期? (必问)1.1 什么是vue⽣命周期?1.2 vue⽣命周期都有哪些钩⼦函数?这些钩⼦函数如何触发?1.3 项⽬开发过程中,在⽣命周期⾥⾯都分别做过什么功能?1.4 ⻚⾯第⼀次加载时⽗⼦组件⽣命周期执⾏的顺序是什么?⾯试官您好,我先介绍⼀下什么是vue的⽣命周期? 所谓的">
<meta property="og:type" content="article">
<meta property="og:title" content="p9总结">
<meta property="og:url" content="http://example.com/2022/06/20/p9%E6%80%BB%E7%BB%93/index.html">
<meta property="og:site_name" content="GS0401">
<meta property="og:description" content="p9总结在p9中我们背了以前的面试题，以及复习了原生js的使用，以及写的动画，拖拽。⼀、Vue2.0⾯试题  vue⽣命周期? (必问)1.1 什么是vue⽣命周期?1.2 vue⽣命周期都有哪些钩⼦函数?这些钩⼦函数如何触发?1.3 项⽬开发过程中,在⽣命周期⾥⾯都分别做过什么功能?1.4 ⻚⾯第⼀次加载时⽗⼦组件⽣命周期执⾏的顺序是什么?⾯试官您好,我先介绍⼀下什么是vue的⽣命周期? 所谓的">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="">
<meta property="article:published_time" content="2022-06-20T08:51:54.000Z">
<meta property="article:modified_time" content="2022-06-20T08:54:26.188Z">
<meta property="article:author" content="John Doe">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content=""><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/2022/06/20/p9%E6%80%BB%E7%BB%93/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'p9总结',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-06-20 16:54:26'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 6.2.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">27</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr/></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">GS0401</a></span><div id="menus"><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">p9总结</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2022-06-20T08:51:54.000Z" title="发表于 2022-06-20 16:51:54">2022-06-20</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-06-20T08:54:26.188Z" title="更新于 2022-06-20 16:54:26">2022-06-20</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="p9总结"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h2 id="p9总结"><a href="#p9总结" class="headerlink" title="p9总结"></a>p9总结</h2><p>在p9中我们背了以前的面试题，以及复习了原生js的使用，以及写的动画，拖拽。<br>⼀、Vue2.0⾯试题</p>
<ol>
<li>vue⽣命周期? (必问)<br>1.1 什么是vue⽣命周期?<br>1.2 vue⽣命周期都有哪些钩⼦函数?这些钩⼦函数如何触发?<br>1.3 项⽬开发过程中,在⽣命周期⾥⾯都分别做过什么功能?<br>1.4 ⻚⾯第⼀次加载时⽗⼦组件⽣命周期执⾏的顺序是什么?<br>⾯试官您好,我先介绍⼀下什么是vue的⽣命周期? 所谓的vue⽣命周期就是vue实例从创建到销毁的整个过程我们称之为vue的<br>⽣命周期,通过vue的⽣命周期我们可以在不同的阶段进⾏不同的逻辑操作. vue⽣命周期常⽤的钩⼦函数⼀共有8个,分别是创<br>建前后、挂载前后、更新前后以及销毁前后. 分别对应的钩⼦函数为beforeCreate 创建前、 created创建后、beforeMount 挂载<br>前、mounted挂载后、beforeUpdate 更新前、updated更新后、beforeDestory 销毁前、 destoryed销毁后, ⻚⾯⼀开始加载的<br>时候就会触发创建前后和挂载前后的钩⼦函数, ⽽更新的钩⼦函数需要当我们改变data的时候才能触发,⽐如 点击按钮,执⾏⼀<br>个⽅法,在这个⽅式⾥⾯给data⾥⾯属性重新进⾏复制操作,这个时候就会更新的钩⼦函数, 销毁的钩⼦函数必须得当组件进⾏<br>切换的时候就会进⾏销毁.<br>在项⽬开发过程中,我经常使⽤到的钩⼦函数有created,我们经常在created进⾏数据请求,或者获取本地存储的数据,还有⼀些其<br>他的操作. 除了created还有mounted,我们经常在mounted⾥⾯获取dom元素 (有时 候也存在获取不到dom元素的情况,这个时<br>候我们⼀般⽤$nextTick⽅法来解决). 以上就是我对⽣命周期的理解</li>
<li>vuex的理解? (必问) 讲解<br>2.1 什么是vuex?使⽤vuex能够解决什么问题?<br>2.2 vuex的五⼤核⼼是什么?<br>2.3 在组件⾥⾯如何调⽤五⼤核⼼的属性和⽅法?<br>2.4 vuex的执⾏机制是什么?<br>2.5 vuex的弊端是什么?怎么解决?<br>⾯试官您好,接下来我先给您介绍⼀下什么是vuex? 所谓的vuex其实就是vue官⽅给我们提供的⼀个状态管理⼯具,通过vuex我<br>们可以组件之间数据共享的问题. vuex⼀共有5⼤核⼼,分别是state,⾥⾯保存的是状态,也可以理解为是数组, 接下来是getters,<br>他们⽤来获取state⾥⾯的状态,并且可以对state的数据进⾏处理之后在返回,有点类似于vue的计算属性, 接下来还有mutations,<br>他的作⽤主要是⽤来修改state⾥⾯的数据,不过在mutations⾥⾯只能进⾏同步的操作,还有actions,这个actions也可以去改变<br>state的状态,不过在actions⾥⾯定义的⽅法可以进⾏异步操作,最后⼀个是modules,如果当我们的项⽬⽐较⼤的时候,那么保存<br>的状态也会增加,如果都写到index.js⽂件⾥⾯,⽂件的内容就会变得特别臃肿,后期难以维护,所以我们可是使⽤modules进⾏模<br>块化的处理,将多个状态抽离到对应js⽂件⾥⾯,最后在modules进⾏合并,这样后期就⽅便维护了.<br>接下来我在介绍⼀下在组件⾥⾯如何调⽤vuex⾥⾯的属性和⽅法,如果我们要获取state⾥⾯的状态,我们可以通过this.<br>来进行获取 如果要调用 里面的方法 我们可以通过 来进行调用 如果要调用 里面的方法我们需要使用<br>store.commit来触发,如果调⽤actions⾥⾯的⽅法,我们⼀般通过this.$store.dispacth来进⾏触发. 除了这种⽅式以外,我们还可以<br>通过辅助函数的⽅式来进⾏调⽤和触发(mapState, mapMutation,mapAction, mapGetter)<br>我在项⽬当中如果要改变state的状态,我们⼀般是在组件⾥⾯调⽤this.$store.dispatch⽅式来触发actions⾥⾯的⽅法,在actions<br>⾥⾯的⽅法通过commit来调⽤mutations⾥⾯定义的⽅法来改变state,同时这也是vuex的执⾏机制<br>不过vuex也有⼀些弊端,⽐如浏览器刷新的时候,vuex的数据会丢失,我们⼀般结合本地存储来解决,当我们在mutations⾥⾯改变<br>state的时候在通过localStorage或者sessionStorage存储到本地,然后在state的状态的属性值那块写⼀个三元表达式,如果本地存<br>在数据的话则读取本地存储的数据,否则就赋值为null<br>在项⽬当中我⼀般使⽤vuex会保存⽤户信息和token以及其他的⼀些状态. 以上就是我对vuex的理解.</li>
<li>vue路由有⼏种模式?有什么区别?原理是什么?(必问) 讲解<br>⾯试官您好,接下来我给您介绍⼀下vue的路由模式,vue的路由模式⼀共有两种,分别是哈希和history. 他们的区别是hash模式不<br>会包含在http请求当中,并且hash不会重新加载⻚⾯,⽽使⽤history模式的话,如果前端的url和后端发起请求的url不⼀致的话,会 报404错误,所以使⽤history模块的话我们需要和后端进⾏配合.<br>history的原理就是利⽤html5新增的两个特性⽅法,分别是psuhState和replaceState来完成的. 以上就是我对vue路由模式的理解.</li>
<li>vue路由守卫?(必问) 讲解⻚⾯权限<br>⾯试官您好,接下来我给您介绍⼀下vue路由守卫,⾸先呢,所谓的路由守卫就是当我们进⾏⻚⾯跳转的时候会触发的钩⼦函数,<br>我们把它称之为vue路由守卫. vue⼀共给我们提供了三种路由守卫,第⼀种全局路由守卫,第⼆种是组件内路由守卫,第三种路由<br>独享守卫,这个是写在路由⾥⾯. 不管是全局,还是组件以及独享,都会有beforeEach、beforeResolve 、a”erEach 分别表示的意<br>思路由跳转前会触发的钩⼦函数以及进⼊路由的时候,以及进⼊路由之后会触发的钩⼦函数. 这⼏个钩⼦函数⾥⾯都有⼀个回<br>调函数,这个回调函数⾥⾯会有三个参数,分别是to,from,next,分别对应的是要进⼊的路由、离开之前的路由,以及进⼊写⼀个路<br>由<br>在项⽬中我们经常使⽤路由守卫实现⻚⾯的鉴权. ⽐如:当⽤户登录之后,我们会把后台返回的token以及⽤户信息保存到vuex<br>和本地,当⻚⾯进⾏跳转的时候,我们会在路由守卫⾥⾯获取vuex⾥⾯的token,如果token存在的话,我们则使⽤next让他进⼊要<br>跳转的⻚⾯,如果token不存在的话我们使⽤next⽅法让他回到登录⻚<br>以上就是我对vue路由守卫的理解</li>
<li>v-if与v-show的区别?(90%)<br>⾯试官您好,接下来我给您介绍⼀下v-if和v-show的区别? ⾸先v-if和v-show都是控制元素的显示与隐藏, 不过v-if控制元素的显<br>示和隐藏的时候会删除对⽤的dom元素,当每⼀个显示的时候,都会重新创建dom和渲染. ⽽v-show则是通过css的display:none<br>和display:block来控制元素的显示与隐藏. v-if⽐较耗费性能,所以我们涉及到频繁的显示隐藏操作我们建议使⽤v-show,如果不<br>是频繁操作的话,我们可以v-if<br>在项⽬中我会经常使⽤v-if和v-show,⽐如我们在搜索功能的时候,他有⼀个历史记录,这个时候我们根据是否有搜索的结果来判<br>断历史记录的显示与隐藏,这块我就可以使⽤v-if ,当然⽤v-show也可以. 以上就是我对v-if和v-show的理解.</li>
<li>v-for与v-if的优先级那个⾼?如果同时使⽤v-for和v-if怎么解决?(90%) 讲解<br>v-for的优先级⾼. 因为v-for的时候我们才开始渲染dom元素,这个v-if还⽆法进⾏判断.<br>v-for和v-if不能同时使⽤,我们可以通过标签,⽐如div或者template标签来进⾏包裹,把v-if写到包裹的标签上⾯(写到v-for外⾯)</li>
<li>methods、computed和watch的区别?(90%)。讲解<br>⾸先呢,methods是⽤来定义⽅法的区域,methods定义的⽅法需要调⽤才能触发. 不具备缓存⾏<br>⽽computed是计算属性,他依赖于属性值的变化,当属性发⽣改变的时候,计算属性⾥⾯定义的⽅法就会触发,computed具有缓<br>存性,依赖属性值的变化⽽变化. ⽽watch主要是⽤于监听,不具备被缓存性.依赖于数据变化⽽触发.<br>在项⽬中,⽐如我们获取state的状态的时候我们会把它放到computed⾥⾯,或者在写购物⻋数量计算的时候也会使⽤计算属性. ⽽watch也在项⽬经常使⽤,⽐如我们封装编辑 和 新增弹窗组件的时候会通过watch来进⾏id判断我们要显否要清空表单的数<br>据.<br>以上就是我对computed和watch的理解.</li>
<li>vue组件通信?(必问)。eventBus 讲解<br>⽗传⼦ 在⼦组件的标签上定义属性 ⼦组件通过props来进⾏接受,可以通过数组的⽅式进⾏接受,也可以通过对象的⽅式来进<br>⾏接收,如果⽗组件没有传递属性,⼦组件可以default来设置默认值<br>⼦传⽗ ⼦组件通过this.$emit(“⾃定义的事件”,要传给⽗组件的数据), ⽗组件通过⼦组件的标签监听⾃定义的时间,通过⽅法来<br>接收传递的数据<br>⾮⽗⼦组件通信<br>通过中央事件总线,我们也称之为eventBus,<br>我们需要创建⼀个空的js⽂件,在这个⽂件⾥⾯创建空的vue实例,然后导出这个空的vue实例,通过实例对象调⽤.on⽅法进⾏接<br>收,通过emit⽅法来进⾏发送,以上就是⾮⽗⼦组件通信的⽅式</li>
<li>$nextTick⽅法有什么作⽤?(80%) 讲解<br>⾸先呢, 也叫做异步更新队列方法 而 方法的主要作用就是等待 元素加载完毕之后才会执行的回调函数 我们经常会在<br>nextTick⽅法⾥⾯获取dom元素</li>
<li>说⼀下什么是mvvm模式?(70%)<br>MVVM 是把 MVC 的 Controller 和 MVP 的 Presenter 改成了 ViewModel 。<br>View 的变化会⾃动更新到 ViewModel ， ViewModel 的变化也会⾃动同步到 View 上显示。这种⾃动<br>同步是因为 ViewModel 中的属性实现了 Observer ，当属性变更时都能触发对应的操作</li>
<li>vue双向数据绑定原理?(必问) 过⼀下<br>vue.js 则是采⽤ 数据劫持 结合 发布者-订阅者 模式的⽅式，<br>通过 Object.defineProperty() 来劫持各个属性的 setter ， getter ，<br>在数据变动时发布消息给订阅者，触发相应的监听回调。<br>这个时候就可以实现数据的双向绑定</li>
<li>vue常⽤的指令有哪些?(50%)<br>v-if<br>v-show<br>v-html<br>v-text<br>v-on<br>v-bind<br>v-model<br>v-for</li>
<li>vue常⽤的修饰符有哪些?(50%)<br>.trim 去除⾸尾多余的空格<br>.stop 阻⽌事件冒泡<br>.once 只渲染⼀次<br>.self 事件只作⽤在元素本身<br>.number 将值转化为number类型<br>.capter 组件之间捕获<br>.prevent 阻⽌元素的默认⾏为<br>.native 事件穿透,让我们可以在⾃定义组件上定义事件和⽅法</li>
<li>vue如何封装可复⽤的组件?以及请举例说明你封装过的组件?(50%) 讲解</li>
<li>分析项⽬的所有⻚⾯结构和业务功能,抽离出相同的⻚⾯结构和业务功能</li>
<li>在src⽬录下创建⼀个components这个的⽂件夹</li>
<li>在这个⽂件夹内创建可复⽤的组件</li>
<li>在需要的⽤的组件⾥⾯引⼊创建的这个可复⽤的组件,并进⾏注册,以标签的形式写在对应的地⽅</li>
<li>接下来就需要对可复⽤的组件内容要进⾏封装,那么在封装的时候我们要注意组件的封闭性和开放性以及粗细粒度</li>
<li>所谓的这个封闭性就是当我们在组件内部定义好之后外部是⽆法进⾏修改的,⽐如当前有⼀个关闭的符号,或者有⼀个箭<br>头,我们需要不管任何⼈使⽤该组件时候都能够显示这个箭头,⽆法从外部进⾏修改</li>
<li>所谓的开放性就是我们需要将动态的内容以及组件通信的⽅式进⾏数据传递,保证组件的可扩展性</li>
<li>⽽所谓的粗细⼒度就是我们可以把⼀整个⻚⾯当作⼀个组件去进⾏封装,也可以⼀个⻚⾯包含了多个组件,⾄于到底选择<br>哪种呢,这个是没有⼀个标准的,我们需要根据⾃⼰的业务需求去进⾏判断</li>
<li>总结来说,所谓的如何封装可复⽤组件其实技术核⼼就是通过我们vue提供的组件通信在结合slot插槽来进⾏分装</li>
<li>⽐如:封装⼀个搜索框组件:</li>
<li>在components⾥⾯创建search.vue</li>
<li>在search.vue⾥⾯实现搜索框的布局</li>
<li>在props⾥⾯接受 title, bgColor, size , icon,以及当点击搜索按钮或者点击回⻋键的时候,触发⼀个⽅法,通过<br>this.$emit将输⼊框输⼊的值传递给⽗组件</li>
<li>接下来要使⽤这个搜索组件,我们需要通过import 在⽗组件内引⼊⼦组件,并在componetns属性⾥⾯进⾏注册,</li>
<li>在⻚⾯就可以使⽤,这个时候我们可以通过传递titile⽼控制⼦组件搜索框显示的内容,通过bgcolor可以控制搜索框<br>的背景颜⾊,也可以通过size设置搜索框字体的⼤⼩,也可以通过icon来设置搜索框的图标, 通过监听$emit⾥⾯定义<br>的⽅法来获取搜索框输⼊的值<br>以上就是封装的过程</li>
<li>vue中key的作⽤是什么?(必问)。过⼀下<br>避免dom元素重复渲染. 我⻔⼀般在设置key的时候⾸先尽量会设置为id,或者index下表.</li>
<li>说⼀下你对keep-alive的理解?以及在项⽬中如何使⽤?(90%) 过⼀下<br>keep-alive是vue内置的⼀个组件，⽽这个组件的作⽤就是能够缓存不活动的组件，我们能够知道，⼀般情况下，组件进⾏切<br>换的时候，默认会进⾏销毁，如果有需求，某个组件切换后不进⾏销毁，⽽是保存之前的状态，⽐如说刚刚填好的表单数<br>据。那么就可以利⽤keep-alive来实现<br>在搭建 vue 项⽬时，有某些路由组件没必要多次渲染，所以需要将组件在内存中进⾏‘持久化’，此时在router-view上使⽤<br>keep-alive。 keep-alive可以使被包含的路由组件状态维持不变，即便是组件切换了，其内的状态依旧维持在内存之中。在下<br>⼀次显示时，也不会重新渲染。<br>include - 字符串或正则表达式。只有名称匹配的组件会被缓存。 exclude - 字符串或正则表达式。任何名称匹配的组件都不会<br>被缓存。 max-数字最多可以缓存多少组件。<br>以上就是我对keep-alive的理解</li>
<li>说⼀下什么是vue过滤器? 有⼏种?项⽬中如何使⽤,请举例说明?(60%)<br>所谓的vue过滤器就是将数据进⾏⼆次处理,得到我们想要的结果数据<br>vue的过滤器分为两种,第⼀种是全局过滤器,通过vue.filet来进⾏定义,第⼆种是局部过滤器,需要定义在组件内部<br>项⽬中我们通过过滤器将后台返回的状态0 和1 转化为⽀付或者未⽀付</li>
<li>说⼀下你对slot插槽的理解?(70%) 过⼀下<br>⾸先呢,所谓的插槽就是⼀个占位符,将⾃定义组件的内容展示出来.我们知道⾃定义的组件⾥⾯如果写内容的话,⻚⾯是不会显<br>示出来的,如果我们想让⾃定义组件⾥⾯的内容显示出来,我们就需要使⽤slot的插槽.<br>⽽插槽分别具名插槽和匿名插槽、以及作⽤域插槽. 我们⽤的⽐较多的具名插槽和匿名插槽,具名插槽需要所有slot标签上指定<br>name属性,⽽在对应标签上添加v-slot属性.<br>在项⽬中我们⼀般在进⾏组件封装的时候会使⽤插槽,以上就是我对插槽的理解.</li>
<li>说⼀下vue中本地跨域如何解决?线上跨域如何解决?(必问) 线上在讲解⼀下<br>本地跨域是通过在vue.config.js⽂件⾥⾯的devServer属性⾥⾯的proxy属性⾥⾯配置,⼀共配置三个属性,分别是代理名称 代理<br>地址 开启跨域 重写路径<br>线上跨域是在nginx.conf⽂件⾥⾯配置, 代理名称是通过location 代理名称。proxy_pass 代理地址</li>
<li>说⼀下如何对axios进⾏⼆次封装?以及api如何封装?(30%)</li>
<li>在src⽂件夹内创建utils⽂件夹</li>
<li>在utils⽂件夹内创建request.js⽂件</li>
<li>在request.js内引⼊axios</li>
<li>使⽤axios.create⽅法创建axios的实例,在axios.create⽅法⾥⾯可以配置请求的公共地址和超时时间以及其他的⼀些配置</li>
<li>在创建请求拦截器和响应拦截器</li>
<li>在请求拦截器⾥⾯可以获取vuex的token,并通过config.header.token &#x3D; vuex的token,将token发送给后台</li>
<li>在请求拦截器⾥⾯我们配置loading加载</li>
<li>在响应拦截器⾥⾯我们可以结束loading加载以及token的过期处理,以及错误响应信息的处理</li>
<li>最后通过export default 导出axios的实例对象</li>
<li>在src⽂件内创建api⽂件夹</li>
<li>在api⽂件夹内创建对应模块的js⽂件</li>
<li>在对应的⽂件⾥⾯引⼊request.js⽂件</li>
<li>封装api⽅法</li>
<li>最后通过export default 导出封装的api⽅法</li>
<li>说⼀下axios的拦截器的作⽤?应⽤场景都有哪些?(80%)<br>⾸先呢,axios拦截器是axios给我们提供的两个⽅法,通过这两个⽅法我们可以对请求发送之前以及响应之后进⾏逻辑的再次处<br>理(拦截). 这两个拦截器不需要⼿动触发,只要发送http请求的时候就会⾃动触发. 我在项⽬中经常通过拦截器发送token, 对<br>token进⾏过期处理,以及进⾏其他的⼀些操作</li>
<li>说⼀下vue和jquery的区别?(50%)<br>⾸先呢jquery他是⽤js封装的⼀个类库,主要是为了⽅便操作dom元素,⽽vue他是⼀个框架,并且呢,他会从真实dom构建出⼀个<br>虚拟的dom树,通过di!算法渲染只发⽣改变的dom元素,其他的相同的dom元素不⽤在重新渲染. ⽽使⽤jquery去改变dom元素<br>的时候,即使有相同的dom元素也会重新渲染,以上就是我对vue和jquery区别的理解.</li>
<li>vue中data发⽣变化,视图不更新如何解决?(必问) 过⼀下<br>⾯试官,您好,接下来我先给您介绍⼀下为什么data发⽣变化,视图不更新,因为Vue实例中的数据是响应式的**⽽我们新增的属<br>性并不是响应式的，由于受现在JavaScript的限制，Vue⽆法检测到属性的新增或删除。所以有时⽆法实时的更新到视图上。<br>**<br>所以我在项⽬中遇到这类问题的时候⼀般是通过this. 方法去解决 $set⽅法⼀共有三个参数,分别是⽬前属性,新增属性,<br>新增的值.<br>以上就是我对视图不更新的理解.</li>
<li>为什么vue中data必须是⼀个函数?(必问) 过⼀下<br>如果data是⼀个函数的话，这样每复⽤⼀次组件，就会返回⼀份新的data，类似于给每个组件实例创建⼀个私有的数据空<br>间，让各个组件实例维护各⾃的数据。⽽单纯的写成对象形式，就使得所有组件实例共⽤了⼀份data，就会造成⼀个变了全<br>都会变的结果。<br>所以说vue组件的data必须是函数。这都是因为js的特性带来的，跟vue本身设计⽆关。<br>25.MVVM模式的优点以及与MVC模式的区别?<br>MVVM模式的优点：<br>1、低耦合： 视图（View）可以独⽴于 Model 变化和修改，⼀个 ViewModel 可以绑定到不同的”View”上，当View变化的时候Model<br>可以不变，当Model变化的时候View也可以不变。<br>2、可重⽤性： 你可以把⼀些视图逻辑放在⼀个ViewModel⾥⾯，让很多 view 重⽤这段视图逻辑。<br>3、独⽴开发： 开发⼈员可以专注于业务逻辑和数据的开发（ViewModel），设计⼈员可以专注于⻚⾯设计。<br>4、可测试： 界⾯素来是⽐较难于测试的，⽽现在测试可以针对ViewModel来写。<br>MVVM 和 MVC 的区别：<br>mvc 和 mvvm 其实区别并不⼤。都是⼀种设计思想。<br>主要区别<br>mvc 中 Controller演变成 mvvm 中的 viewModel，<br>mvvm 通过数据来显示视图层⽽不是节点操作。<br>mvvm主要解决了:<br>mvc中⼤量的DOM 操作使⻚⾯渲染性能降低，加载速度变慢，影响⽤户体验。</li>
<li>怎样理解 Vue 的单向数据流?<br>数据总是从⽗组件传到⼦组件，⼦组件没有权利修改⽗组件传过来的数据，只能请求⽗组件对原始数据进⾏修改。这样会防⽌从<br>⼦组件意外改变⽗级组件的状态，从⽽导致你的应⽤的数据流向难以理解。<br>注意：在⼦组件直接⽤ v-model 绑定⽗组件传过来的 prop 这样是不规范的写法 开发环境会报警告<br>如果实在要改变⽗组件的 prop 值 可以再 data ⾥⾯定义⼀个变量 并⽤ prop 的值初始化它 之后⽤$emit 通知⽗组件去修改</li>
<li>虚拟 DOM 是什么? 有什么优缺点?<br>什么是虚拟dom?<br>由于在浏览器中操作 DOM 是很昂贵的。频繁的操作 DOM，会产⽣⼀定的性能问题. 所以在vue中将真实的DOM节点抽离成⼀个虚拟<br>的DOM树,这个虚拟的DOM树就是虚拟DOM.<br>优点:<br>保证性能下限： 框架的虚拟 DOM 需要适配任何上层 API 可能产⽣的操作，它的⼀些 DOM 操作的实现必须是普适的，所以它<br>的性能并不是最优的；但是⽐起粗暴的 DOM 操作性能要好很多，因此框架的虚拟 DOM ⾄少可以保证在你不需要⼿动优化的<br>情况下，依然可以提供还不错的性能，即保证性能的下限；<br>⽆需⼿动操作 DOM： 我们不再需要⼿动去操作 DOM，只需要写好 View-Model 的代码逻辑，框架会根据虚拟 DOM 和 数据双向<br>绑定，帮我们以可预期的⽅式更新视图，极⼤提⾼我们的开发效率；<br>跨平台： 虚拟 DOM 本质上是 JavaScript 对象,⽽ DOM 与平台强相关，相⽐之下虚拟 DOM 可以进⾏更⽅便地跨平台操作，例如<br>服务器渲染、weex 开发等等。<br>缺点:<br>⽆法进⾏极致优化： 虽然虚拟 DOM + 合理的优化，⾜以应对绝⼤部分应⽤的性能需求，但在⼀些性能要求极⾼的应⽤中虚拟<br>DOM ⽆法进⾏针对性的极致优化。<br>⾸次渲染⼤量 DOM 时，由于多了⼀层虚拟 DOM 的计算，会⽐ innerHTML 插⼊慢</li>
<li>Vue的di!算法原理是什么？<br>Vue的di!算法是平级⽐较，不考虑跨级⽐较的情况。内部采⽤深度递归的⽅式+双指针⽅式⽐较<br>先⽐较两个节点是不是相同节点<br>相同节点⽐较属性，复⽤⽼节点<br>先⽐较⼉⼦节点，考虑⽼节点和新节点⼉⼦的情况<br>优化⽐较：头头、尾尾、头尾、尾头<br>⽐对查找，进⾏复⽤<br>29.组件写name有啥好处？<br>增加name属性，会在components属性中增加组件本身，实现组件的递归调⽤。<br>可以表示组件的具体名称，⽅便调试和查找对应的组件。<br>⼆、微信⼩程序⾯试题</li>
<li>⼩程序有⼏个⽂件？<br>WXML ：微信⾃⼰定义的⼀套组件<br>WXSS : ⽤于描述 WXML 的组件样式<br>js : 逻辑处理<br>json : ⼩程序⻚⾯配置<br>2 ⼩程序怎么跟随事件传值<br>在 ⻚⾯标签上通过 绑定 dataset-key &#x3D; value ， 然后绑定点击通过 e.currentTarget.dataset.key 来获取标签上<br>绑定的值。<br>3 ⼩程序WXSS与CSS 的区别<br>WXSS WXSS<br>wxss 背景图⽚只能引⼊外链，不能使⽤本地图⽚<br>⼩程序样式使⽤ @import 引⼊ 外联样式⽂件，地址为相对路径。<br>尺⼨单位为 rpx , rpx 是响应式像素,可以根据屏幕宽度进⾏⾃适应。<br>4 ⼩程序的双向绑定和Vue哪⾥不⼀样?<br>⼩程序 直接使⽤ this.data.key &#x3D; value 是 不能更新到视图当中的。 必须使⽤ this.setData({ key ：value })<br>来更新值。<br>5 ⼩程序的⽣命周期函数<br>onLoad : ⻚⾯加载时触发。⼀个⻚⾯只会调⽤⼀次，可以在 onLoad 的参数中获取打开当前⻚⾯路径中的参数<br>onShow : ⻚⾯显示 &#x2F; 切⼊前台时触发调⽤。<br>onReady : ⻚⾯初次渲染完成时触发,⼀个⻚⾯只会调⽤⼀次。<br>onHide : ⻚⾯隐藏 &#x2F; 切⼊后台时触发，如 navigateTo 或底部 tab 切换到其他⻚⾯，⼩程序切⼊后台等<br>onUnload : ⻚⾯卸载时触发。如 redirectTo 或 navigateBack 到其他⻚⾯时.<br>6 ⼩程序怎么实现下拉刷新<br>两种⽅案 ⽅案 ⼀ ：<br>通过在 app.json 中， 将 “enablePullDownRefresh”: true, 开启全局下拉刷新。<br>或者通过在 组件 .json ， 将 “enablePullDownRefresh”: true, 单组件下拉刷新。<br>⽅案⼆：<br>scroll-view ：使⽤该滚动组件 ⾃定义刷新，通过 bindscrolltoupper 属性， 当滚动到顶部&#x2F;左边，会触发<br>scrolltoupper 事件，所以我们可以利⽤这个属性，来实现下拉刷新功能。</li>
<li>⼩程序有哪些传递数据的⽅法</li>
<li>使⽤全局变量<br>在 app.js 中的 this.globalData &#x3D; { } 中放⼊要存储的数据。<br>在 组件.js 中， 头部 引⼊ const app &#x3D; getApp(); 获取到全局变量<br>直接使⽤ app.globalData.key 来进⾏赋值和获取值。<br><button bindtap="get" data-name="测试"> 拿到传值</button><br>get(e){<br> console.log(e.currentTarget.dataset.name)<br> },<br>12345</li>
<li>使⽤ 路由<br>wx.navigateTo 和 wx.redirectTo 时，可以通过在 url 后 拼接 + 变量， 然后在 ⽬标⻚⾯ 通过在 onLoad 周期<br>中，通过参数来获取传递过来的值。</li>
<li>使⽤本地缓存</li>
<li>简述下wx.navigateTo(),wx.redirectTo(),wx.switchTab(),wx.navigateBack(),wx.reLaunch() 区 别<br>wx.navigateTo() : 保留当前⻚⾯，跳转到应⽤内的某个⻚⾯。但是不能跳到 tabbar ⻚⾯<br>wx.redirectTo() : 关闭当前⻚⾯，跳转到应⽤内的某个⻚⾯。但是不允许跳转到 tabbar ⻚⾯<br>wx.switchTab() : 跳转到 TabBar ⻚⾯，并关闭其他所有⾮ tabBar ⻚⾯<br>wx.navigateBack() : 关闭当前⻚⾯，返回上⼀⻚⾯或多级⻚⾯。可通过 getCurrentPages() 获取当前的⻚⾯栈，决<br>定需要返回⼏层<br>wx.reLaunch() : 关闭所有⻚⾯，打开到应⽤的某个⻚⾯。</li>
<li>⼩程序wx:if和 hidden&#96;的区别<br>wx:if : 有更⾼的切换消耗。<br>hidden : 有更⾼的初始渲染消耗。<br>使⽤<br>频繁切换使⽤ hidden , 运⾏时条件变化使⽤ wx: if</li>
<li>app.json全局配置⽂件描述<br>pages : ⽤于存放当前⼩程序的所有⻚⾯路径<br>window : ⼩程序所有⻚⾯的顶部背景颜⾊，⽂字颜⾊配置。<br>tabBar : ⼩程序底部的 Tab ,最多5个，最少2个。</li>
<li>如何封装⼩程序请求<br>封装 wx.request 请求传递需要的参数( url , data , method , success 成功回调 ， fail 失败回调 ) , 封装常⽤⽅<br>法 POST , GET , DELETE , PUT …. 最后导出这些⽅法<br>然后新建⼀个 api.js ⽂件，导⼊封装好的⽅法，然后调取相应的⽅法，传递数据。<br>wx.request 封装<br>var app &#x3D; getApp(); &#x2F;&#x2F;获取⼩程序全局唯⼀app实例<br>var host &#x3D; ‘******************’; &#x2F;&#x2F;接⼝地址<br>&#x2F;&#x2F;POST请求<br>function post(url, data, success,fail) {<br> request(url, postData, “POST”, doSuccess, doFail);<br>}<br>&#x2F;&#x2F;GET请求<br>function get(url, data, success, fail) {<br> request(url, postData, “GET”, doSuccess, doFail);<br>}<br>function request(url, data, method, success, fail) {<br>123456789<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>组件使⽤ 封装好的请求<br> wx.showLoading({<br> title: “正在加载中…”,<br> })<br> wx.request({<br> url: host + url, &#x2F;&#x2F;请求地址<br> method: method, &#x2F;&#x2F;请求⽅法<br> header: { &#x2F;&#x2F;请求头<br> “Content-Type”: “application&#x2F;json;charset&#x3D;UTF-8”<br> },<br> data: data, &#x2F;&#x2F;请求参数<br> dataType: ‘json’, &#x2F;&#x2F;返回数据格式<br> responseType: ‘text’, &#x2F;&#x2F;响应的数据类型<br> success: function(res) {<br> wx.hideLoading();<br> &#x2F;&#x2F;成功执⾏⽅法，参数值为res.data,直接将返回的数据传⼊<br> success(res.data);<br> },<br> fail: function() {<br> &#x2F;&#x2F;失败执⾏⽅法<br> fail();<br> },<br> })<br>}<br>module.exports &#x3D; {<br> postRequest: post,<br> getRequest: get, }<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>34<br>35<br>36<br>37<br>38<br>39<br>40<br>41<br>42<br>43<br>var http &#x3D; require(‘..&#x2F;..&#x2F;utils&#x2F;request.js’); &#x2F;&#x2F;相对路径<br>var params &#x3D; {&#x2F;&#x2F;请求参数<br> id:this.data.userId<br>}<br>http.postRequest(“user&#x2F;delUser”, params, function(res) {<br> console.log(“修改成功！”);</li>
</ol>
<p>}, function(res) {<br> console.log(“修改失败！！！”)<br>})<br>123456789<br>10<br>11<br>12</p>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="http://example.com">John Doe</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="http://example.com/2022/06/20/p9%E6%80%BB%E7%BB%93/">http://example.com/2022/06/20/p9%E6%80%BB%E7%BB%93/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="http://example.com" target="_blank">GS0401</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/gh/overtrue/share.js@master/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2022/06/20/p10%E6%80%BB%E7%BB%93/"><img class="prev-cover" src="" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">p10总结</div></div></a></div><div class="next-post pull-right"><a href="/2022/06/20/p8%E6%80%BB%E7%BB%93/"><img class="next-cover" src="" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">p8总结</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">John Doe</div><div class="author-info__description"></div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">27</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/xxxxxx"><i class="fab fa-github"></i><span>Follow Me</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#p9%E6%80%BB%E7%BB%93"><span class="toc-number">1.</span> <span class="toc-text">p9总结</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/2022/06/21/nginx%E7%9A%84%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/" title="nginx的基础入门"><img src="" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="nginx的基础入门"/></a><div class="content"><a class="title" href="/2022/06/21/nginx%E7%9A%84%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/" title="nginx的基础入门">nginx的基础入门</a><time datetime="2022-06-20T23:49:26.000Z" title="发表于 2022-06-21 07:49:26">2022-06-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/06/21/vue3/" title="vue3"><img src="" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="vue3"/></a><div class="content"><a class="title" href="/2022/06/21/vue3/" title="vue3">vue3</a><time datetime="2022-06-20T23:48:21.000Z" title="发表于 2022-06-21 07:48:21">2022-06-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/06/21/%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF%E5%BC%80%E5%8F%91%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%90%88%E5%B9%B6/" title="使用分支开发功能，合并"><img src="" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="使用分支开发功能，合并"/></a><div class="content"><a class="title" href="/2022/06/21/%E4%BD%BF%E7%94%A8%E5%88%86%E6%94%AF%E5%BC%80%E5%8F%91%E5%8A%9F%E8%83%BD%EF%BC%8C%E5%90%88%E5%B9%B6/" title="使用分支开发功能，合并">使用分支开发功能，合并</a><time datetime="2022-06-20T23:47:54.000Z" title="发表于 2022-06-21 07:47:54">2022-06-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/06/21/git%E7%9A%84%E9%AB%98%E7%BA%A7%E6%93%8D%E4%BD%9C/" title="git的高级操作"><img src="" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="git的高级操作"/></a><div class="content"><a class="title" href="/2022/06/21/git%E7%9A%84%E9%AB%98%E7%BA%A7%E6%93%8D%E4%BD%9C/" title="git的高级操作">git的高级操作</a><time datetime="2022-06-20T23:46:37.000Z" title="发表于 2022-06-21 07:46:37">2022-06-21</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/2022/06/20/p10%E6%80%BB%E7%BB%93/" title="p10总结"><img src="" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="p10总结"/></a><div class="content"><a class="title" href="/2022/06/20/p10%E6%80%BB%E7%BB%93/" title="p10总结">p10总结</a><time datetime="2022-06-20T08:54:35.000Z" title="发表于 2022-06-20 16:54:35">2022-06-20</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2022 By John Doe</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js"></script><div class="js-pjax"></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>